package com.jxpanda.commons.base;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;

/**
 * Mybatis的BaseMapper的扩展
 * 因为默认开启了逻辑删除
 *
 * 扩展中提供了在开启逻辑删除的情况下，使用物理删除的能力
 * 以及一些其他常用的简单SQL扩展（例如：单字段求和）
 *
 * @author Panda
 */
public interface Mapper<T> extends BaseMapper<T> {

    /**
     * 物理上是否存在
     *
     * @param tableName 表名，一般是从entity上自动解析传递过来
     * @param id        主键ID
     * @return 物理上是否存在这条数据
     */
    @Select("SELECT COUNT(*) FROM ${tableName} WHERE id = ${id}")
    Boolean isPhysicalExisting(@Param("tableName") String tableName, @Param(Entity.ID) Serializable id);

    /**
     * 提供物理删除能力
     * 利用mybatis-plus的wrapper删除
     *
     * @param tableName 表名，一般是从entity上自动解析传递过来
     * @param wrapper   Wrapper对象
     * @return 删除是否成功
     */
    @Delete("DELETE FROM ${tableName} ${ew.customSqlSegment}")
    Boolean destroy(@Param("tableName") String tableName, @Param(Constants.WRAPPER) Wrapper<T> wrapper);

    /**
     * 提供物理删除能力
     * 基于主键ID删除
     *
     * @param tableName 表名，一般是从entity上自动解析传递过来
     * @param id        主键ID
     * @return 删除是否成功
     */
    @Delete("DELETE FROM ${tableName} WHERE id = ${id}")
    Boolean destroyById(@Param("tableName") String tableName, @Param(Entity.ID) Serializable id);

    /**
     * 提供物理删除能力
     * 用主键ID批量删除
     *
     * @param tableName 表名，一般是从entity上自动解析传递过来
     * @param ids       主键ID的列表
     * @return 删除是否成功
     */
    @Delete("<script>DELETE FROM ${tableName} WHERE id IN (<foreach collection=\"ids\" item=\"id\" separator=\",\">#{id}</foreach>)</script>")
    Boolean destroyByIds(@Param("tableName") String tableName, @Param("ids") Collection<? extends Serializable> ids);

    /**
     * 提供求和能力
     *
     * @param tableName 表名，一般是从entity上自动解析传递过来
     * @param field     字段，用哪个字段求和
     * @param wrapper   Wrapper对象，筛选条件
     * @return 求和后的值
     */
    @Select("SELECT SUM(${field}) FROM ${tableName} ${ew.customSqlSegment}")
    BigDecimal sum(@Param("tableName") String tableName, @Param("field") String field, @Param(Constants.WRAPPER) Wrapper<T> wrapper);

}
